package com.qf.drtest.utils;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

public class ThreadPoolUtils {

    /*
        线程池其他问题：
            1、submit和execute区别？
            2、线程池中任务一旦出现异常后，线程池会怎样处理
            3、线程池中Worker类的原理
     */

    /**
     * 炒菜的任务线程池
     */
    private static ThreadPoolExecutor tp;
    /**
     * 煮饭的任务线程池
     */
    private static ThreadPoolExecutor tp2;

    static {
        /*
            对tp进行初始化

            cpu想象成包工头
            任务想象成搬砖的工人
                工人负责的工作很繁琐，干起来很慢  --
                工人负责的工作很简单，干起来很快  --


            线程数量的设置： 线程执行是由cpu进行调度的
                计算型任务：（很快，基本没有阻塞）-- cpu核数+1
                io型任务：（很慢，有长时间阻塞） -- 2*cpu核数

                以上这种规则属于通用的理论值，具体的数量和这个值偏差不大的，如果追求更极致的性能，我们需要进行压测

            线程池7大参数:
              int corePoolSize,  核心线程数   3
              int maximumPoolSize,  最大线程数  5
              long keepAliveTime,  存活时间
              TimeUnit unit,   存活时间的单位
              BlockingQueue<Runnable> workQueue,  任务的缓存队列  10
              ThreadFactory threadFactory,  线程工厂
              RejectedExecutionHandler handler  拒绝策略
                AbortPolicy: 报异常拒绝 (如果任务的功能非常重要，选这个拒绝策略，可以通过异常立马感知到)
                CallerRunsPolicy: 任务是在哪个线程中提交的，就交给哪个线程执行
                DiscardOldestPolicy: 将任务的缓存队列最老的那个干掉，自己入队等待(不太重要的任务，选择这个)
                DiscardPolicy: 悄悄的丢掉任务

            线程池的工作流：

         */

        tp = new ThreadPoolExecutor(5,
                5,
                0,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(),
                new CustemThreadFactory("炒菜"),
                new ThreadPoolExecutor.DiscardPolicy()
                );

        tp2 = new ThreadPoolExecutor(5,
                5,
                0,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(),
                new CustemThreadFactory("煮饭"),
                new ThreadPoolExecutor.DiscardPolicy()
                );

    }

    public static ThreadPoolExecutor tp(){
        return tp;
    }
    public static ThreadPoolExecutor tp2(){
        return tp2;
    }

    /**
     * 自定一线程工厂
     *  目的： 可以自定义线程的名称，在项目运行过程中， 通过线程名称可以快速定位出现异常的任务类型
     */
    static class CustemThreadFactory implements ThreadFactory {
        private static final AtomicInteger poolNumber = new AtomicInteger(1);
        private final ThreadGroup group;
        private final AtomicInteger threadNumber = new AtomicInteger(1);
        private final String namePrefix;

        CustemThreadFactory(String prefix) {
            SecurityManager s = System.getSecurityManager();
            group = (s != null) ? s.getThreadGroup() :
                    Thread.currentThread().getThreadGroup();
            namePrefix = prefix +
                    poolNumber.getAndIncrement() +
                    "-thread-";
        }

        public Thread newThread(Runnable r) {
            Thread t = new Thread(group, r,
                    namePrefix + threadNumber.getAndIncrement(),
                    0);
            if (t.isDaemon())
                t.setDaemon(false);
            if (t.getPriority() != Thread.NORM_PRIORITY)
                t.setPriority(Thread.NORM_PRIORITY);
            return t;
        }
    }
}
